/**
 *
 */
package hu.myai.indicators;

import hu.myai.api.indicators.AbstractIndicator;
import hu.myai.model.IndicatorVO;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author bozbalint
 * 
 *         This calculation built on <br>
 *         - moving average(MovingAverageIndicator) <br>
 *         indicators.
 * */
public class StandardDeviationIndicator extends AbstractIndicator {

    /**
     * The object used when logging debug,errors,warnings and info.
     * */
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    public StandardDeviationIndicator(Double parameter) {
        super(parameter);
    }

    private String movingAveID;

    @Override
    public void init() {
        // I expect MovingAverage registered indicator
        movingAveID = register(new MovingAverageIndicator(parameter));
    }

    /**
     * The steps for calculating a 20-period standard deviation are as follows: <br>
     * <br>
     * 1. Calculate the simple average (mean) of the closing price. i.e., Sum of
     * the last 20 closing prices then divide it by 20. <br>
     * 2. For each period, subtract the average closing price from the actual
     * closing price. This gives us the deviation for each period. <br>
     * 3. Square each period's deviation. <br>
     * 4. Sum the squared deviations. <br>
     * 5. Divide the sum of the squared deviations by the number of periods (20
     * in our case). <br>
     * 6. The standard deviation is then equal to the square root of that
     * number.
     * */

    @Override
    protected IndicatorVO indicatorCalculation() {

        // I expect X_MovingAverage registered indicator
        IndicatorVO movIndicator = indicatorMap.get(movingAveID);
        if (movIndicator == null) {
            return null;
        }

        double sumSquare = 0;
        for (int i = 0; i < parameter.intValue(); i++) {

            double hTickValue = tickHistory.get(i).getClose();

            double deviation = hTickValue - movIndicator.getValue();
            sumSquare += deviation * deviation;
        }

        double standardDeviation = Math.sqrt(sumSquare / parameter);

        IndicatorVO indicator = new IndicatorVO();
        indicator.setValue(standardDeviation);
        indicator.setChanged(true);
        indicator.setDate(lastTick.getTime());

        log.debug(indicator.toString());
        return indicator;
    }
}
